import { Button } from "../ui/button";
import microphoneOpen from "@/assets/microphone-open.svg";
import microphoneClose from "@/assets/microphone-close.svg";
import close from "@/assets/close.svg";
import { useEffect, useRef, useState } from "react";
import clsx from "clsx";
import { twMerge } from "tailwind-merge";
import { useConversationStore } from "@/store/useConversationStore";
import { useSpeechSegments } from "@/hooks/useSilenceDetector";
import type { WSClient } from "@/utils/ws";
import { createWS, sendAudioWSMessage } from "@/api/chat";
import { useWSStore } from "@/store/useWSStore";

interface VoiceCallProps {
  onClose: () => void;
}

export default function VoiceCall({ onClose }: VoiceCallProps) {
  const audioRef = useRef<HTMLAudioElement | null>(null);
  const audioContextRef = useRef<AudioContext | null>(null);
  const processorRef = useRef<ScriptProcessorNode | null>(null);
  const audioQueueRef = useRef<Float32Array[]>([]); // PCM 队列

  const ws = useRef<WSClient | null>(null);
  const [isMicOn, setIsMicOn] = useState(true);
  const { selectedId, conversations } = useConversationStore();
  const found = conversations.find((c) => c.id == selectedId);
  const { segments } = useSpeechSegments({ threshold: 10, silenceTime: 1000 });

  useEffect(() => {
    audioContextRef.current = new window.AudioContext();
    const audioContext = audioContextRef.current;

    // 创建播放节点
    const processor = audioContext.createScriptProcessor(4096, 1, 1);
    processor.onaudioprocess = (e) => {
      const output = e.outputBuffer.getChannelData(0);
      output.fill(0); // 先清空

      if (audioQueueRef.current.length > 0) {
        const chunk = audioQueueRef.current.shift()!;
        output.set(chunk.subarray(0, output.length)); // 拷贝数据
        if (chunk.length > output.length) {
          // 如果 chunk 比当前 buffer 大，剩余部分放回队列
          audioQueueRef.current.unshift(chunk.subarray(output.length));
        }
      }
    };

    processor.connect(audioContext.destination);
    processorRef.current = processor;

    return () => {
      processor.disconnect();
      audioContext.close();
    };
  }, []);

  useEffect(() => {
    if (!selectedId) return;
    useWSStore.getState().closeWS(selectedId);

    ws.current = createWS(selectedId, async (event) => {
      if (event instanceof ArrayBuffer) {
        enqueuePCM(event);
      }
    });

    return () => {
      ws.current?.close();
    };
  }, [selectedId]);

  // 把 ArrayBuffer 转 PCM 放进队列
  async function enqueuePCM(arrayBuffer: ArrayBuffer) {
    const audioContext = audioContextRef.current;
    if (!audioContext) return;

    const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
    const channelData = audioBuffer.getChannelData(0);
    audioQueueRef.current.push(new Float32Array(channelData));
  }

  useEffect(() => {
    if (!segments.length) return;
    const segment = segments[segments.length - 1];
    sendAudio(segment);
  }, [segments.length]);

  const sendAudio = async (message: Blob | ArrayBuffer) => {
    let buffer: ArrayBuffer;
    if (message instanceof Blob) buffer = await message.arrayBuffer();
    else buffer = message;

    if (ws.current) {
      sendAudioWSMessage(ws.current, {
        audio: buffer,
        sessionId: Number(selectedId),
        skillId: 0,
      });
    }
  };

  const handleMic = () => setIsMicOn(!isMicOn);

  return (
    <div className="fixed inset-0 z-[9999] bg-white flex flex-col justify-center items-center">
      <div className="relative flex w-full items-center justify-center"></div>
      <div className="relative flex h-full w-full items-center justify-center">
        <div className="flex flex-col items-center gap-4">
          <img
            width={200}
            height={200}
            src={found?.roleAvatarUrl || ""}
            alt="角色头像"
            className="rounded-full"
          />
          <div className="text-2xl font-bold">{found?.roleName}</div>
        </div>
      </div>
      <audio ref={audioRef} hidden controls />
      <div className="mt-5 mb-6 flex justify-center">
        <div className="flex flex-row items-center gap-6 rounded-full px-3 py-1 transition-width duration-200 ease-in-out">
          <Button
            onClick={handleMic}
            className={twMerge(
              "right-4 w-16 h-16 flex items-center justify-center rounded-full font-bold",
              clsx({
                "bg-gray-200 hover:bg-gray-300": isMicOn,
                "bg-red-200 hover:bg-red-300 text-white": !isMicOn,
              })
            )}
          >
            <img
              width={24}
              height={24}
              src={isMicOn ? microphoneOpen : microphoneClose}
              alt="麦克风"
            />
          </Button>
          <Button
            onClick={onClose}
            className="right-4 w-16 h-16 flex items-center justify-center rounded-full bg-gray-200 hover:bg-gray-300 text-black font-bold"
          >
            <img width={24} height={24} src={close} alt="关闭语音调用" />
          </Button>
        </div>
      </div>
    </div>
  );
}
